//require CodeRAD
package com.codename1.samples;


import com.codename1.components.Switch;
import static com.codename1.ui.CN.*;
import com.codename1.ui.Form;
import com.codename1.ui.Dialog;
import com.codename1.ui.Label;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import com.codename1.ui.Toolbar;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.rad.models.Attribute;
import com.codename1.rad.models.Entity;
import static com.codename1.rad.models.EntityTypeBuilder.entityTypeBuilder;
import com.codename1.rad.models.Tag;
import com.codename1.rad.nodes.Node;
import com.codename1.rad.nodes.ViewNode;
import com.codename1.rad.schemas.Thing;
import com.codename1.rad.ui.AbstractEntityView;
import static com.codename1.ui.ComponentSelector.$;
import com.codename1.ui.FontImage;
import com.codename1.ui.layouts.BorderLayout;

/**
 * A sample using CodeRAD to create a simple Model and View where the view changes based
 * on a model property.
 * 
 * <p>See <a href="https://github.com/shannah/CodeRAD">CodeRAD repo</a> for more on CodeRAD.</p>
 * 
 * <p>This sample was created as part of <a href="https://github.com/shannah/CodeRAD/issues/16">this issue.</p>
 * 
 * <p>This file was generated by <a href="https://www.codenameone.com/">Codename One</a> for the purpose 
 * of building native mobile applications using Java.</p>
 * 
 *  
 */
public class RADStatusViewSample {

    private Form current;
    private Resources theme;

    public void init(Object context) {
        // use two network threads instead of one
        updateNetworkThreadCount(2);

        theme = UIManager.initFirstTheme("/theme");

        // Enable Toolbar on all Forms by default
        Toolbar.setGlobalToolbar(true);

        // Pro only feature
        Log.bindCrashProtection(true);

        addNetworkErrorListener(err -> {
            // prevent the event from propagating
            err.consume();
            if(err.getError() != null) {
                Log.e(err.getError());
            }
            Log.sendLogAsync();
            Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
        });        
    }
    
    public void start() {
        if(current != null){
            current.show();
            return;
        }
        Form hi = new Form("Hi World", BoxLayout.y());
        Tag TAG_ONLINE = new Tag("online");
        
        
        class User extends Entity {}
        entityTypeBuilder(User.class)
                .Boolean(TAG_ONLINE)
                .string(Thing.name)
                .factory(cls -> {return new User();})
                .build();
        
        /**
         * A view that displays the status (online/offline) of an entity using
         * the TAG_ONLINE tag. 
         */
        class StatusView extends AbstractEntityView{
            
            // ViewNode.  Not used;
            ViewNode node;
            
            // Flag to indicate the current state online/offline of the view
            private boolean online;
            
            // Label used
            private Label label = new Label();
            
            /**
             * Creates a new StatusView for user model.
             */
            StatusView(User user) {
                super(user);
                this.node = new ViewNode(new Attribute[]{});
                setLayout(new BorderLayout());
                $(this).setMargin(0).setPadding(0);
                this.add(CENTER, label);
                update();
                
            }
            @Override
            public void update() {
                // Check to see if the model is online.
                boolean modelOnline = !getEntity().isFalsey(TAG_ONLINE);
                if (modelOnline != online) {
                    // Model state has changed since last update
                    online = modelOnline;
                    if (online) {
                        label.setText("Online");
                        label.setUIID("OnlineLabel");
                        FontImage.setMaterialIcon(label, FontImage.MATERIAL_CONNECTED_TV);
                    } else {
                        label.setText("Offline");
                        label.setUIID("OfflineLabel");
                        FontImage.setMaterialIcon(label, FontImage.MATERIAL_OFFLINE_BOLT);
                    }
                    Form f = getComponentForm();
                    if (f != null) {
                        // Changing the text in this case may change the layout size
                        // of the status view here, so it is best to just issue a revalidate
                        // for the whole form.  If the status change didn't change
                        // the layout size, then we could have just skipped this step.
                        f.revalidateWithAnimationSafety();
                    }
                }
                
            }

            @Override
            public void commit() {
                // Don't need to implement commit() because this view doesn't 
                // "update" the model - it only shows model stats.
            }

            @Override
            public Node getViewNode() {
                return node;
            }
            
        }
        
        // Create a new user
        User user = new User();
        
        // Create a status view for the user
        StatusView statusView = new StatusView(user);
        
        // Add a UI switch to toggle user state between online and offline
        Switch onlineSwitch = new Switch("Online");
        onlineSwitch.addChangeListener(e->{
            
            // Set the user TAG_ONLINE status.  This will trigger a property
            // change in the model and update the view.
            user.set(TAG_ONLINE, onlineSwitch.isOn());
        });
        
        hi.add(onlineSwitch);
        hi.add(statusView);
        hi.show();
    }

    public void stop() {
        current = getCurrentForm();
        if(current instanceof Dialog) {
            ((Dialog)current).dispose();
            current = getCurrentForm();
        }
    }
    
    public void destroy() {
    }

}
